package com.fortune.conf;

/**
 * @program: fortune
 * @description:
 * @author: wwb
 * @create: 2025-04-29 19:02
 */
import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.io.FileUtil;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.io.FileUtils;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ImageCompressorJava8 {

    public enum ImageFormat {
        JPEG, PNG, WEBP
    }
    private static void validateFileIntegrity(String inputPath) throws IOException {
        try (InputStream is = new FileInputStream(inputPath)) {
            byte[] buffer = new byte[1024];
            while (is.read(buffer) != -1) {} // 完整读取文件触发底层错误
        } catch (IOException e) {
            throw new IOException("文件损坏或格式异常: " + e.getMessage());
        }
    }

    public static void preprocessImage(String input, String output) throws Exception {
        ProcessBuilder pb = new ProcessBuilder(
                "magick",
                input,
                "-strip",        // 移除元数据
                "-auto-orient",  // 修正方向
                "JPG:-",         // 输出标准JPEG
                "|",
                "ffmpeg",
                "-i", "pipe:0",
                "-c:v", "mjpeg",
                output
        );
        executeCommand(pb);
    }

    // 在Java中添加文件校验方法
    public static boolean validateJpeg(String path) {
        try (RandomAccessFile f = new RandomAccessFile(path, "r")) {
            // 检查SOI和EOI标记
            f.seek(0);
            if (f.readShort() != (short)0xFFD8) return false; // SOI
            f.seek(f.length() - 2);
            return f.readShort() == (short)0xFFD9; // EOI
        } catch (Exception e) {
            return false;
        }
    }



    /**
     * 图片压缩核心方法
     * @param inputPath   输入文件路径
     * @param outputPath  输出文件路径
     * @param quality     质量参数 (JPEG:1-100, PNG:0-9, WebP:0-100)
     */
    public static void compressImage(String inputPath,
                                     String outputPath,
                                     int quality) throws Exception {
        // 1. 文件校验
        if (!validateJpeg(inputPath)) {
            throw new IOException("损坏的JPEG文件");
        }

        // 2. 预处理
        String tempFile = "temp_" + System.currentTimeMillis() + ".jpg";
        preprocessImage(inputPath, tempFile);

        // 3. FFmpeg压缩
        List<String> command = new ArrayList<>();
        command.add("ffmpeg");
        command.add("-err_detect");
        command.add("ignore_err");
        command.add("-fflags");
        command.add("+discardcorrupt");
        command.add("-probesize");
        command.add("50M");
        command.add("-analyzeduration");
        command.add("100M");
        command.add("-f");
        command.add("image2");
        command.add("-i");
        command.add(tempFile);
        command.add("-vf");
        command.add("scale='max(1,iw*0.8)':'max(1,ih*0.8)':flags=lanczos");
        command.add("-c:v");
        command.add("mjpeg");
        command.add("-bsf:v");
        command.add("mjpeg2jpeg");
        command.add("-q:v");
        command.add(String.valueOf(quality));
        command.add("-pix_fmt");
        command.add("yuvj420p");
        command.add("-y");
        command.add(outputPath);

        executeCommand(new ProcessBuilder(command));

        // 4. 清理临时文件
        new File(tempFile).delete();
    }

    private static void validateInput(String inputPath, int quality, double scaleRatio)
            throws IOException {
        File inputFile = new File(inputPath);
        if (!inputFile.exists()) {
            throw new IOException("输入文件不存在: " + inputPath);
        }

        if (quality < 0 || quality > 100) {
            throw new IllegalArgumentException("质量参数超出范围 (0-100)");
        }

        if (scaleRatio <= 0 || scaleRatio > 1) {
            throw new IllegalArgumentException("缩放比例必须在0.1-1.0之间");
        }
    }

    private static String normalizePath(String path) {
        return path.replace("\\", "/");
    }

    private static List<String> getFormatParams(ImageFormat format, int quality) {
        List<String> params = new ArrayList<>();
        switch (format) {
            case JPEG:
                params.add("-c:v");
                params.add("mjpeg");
                params.add("-bsf:v");
                params.add("mjpeg2jpeg"); // 转换Motion JPEG为标准JPEG
                params.add("-strict");
                params.add("-2"); // 允许实验性功能
                break;
            case PNG:
                params.add("-compression_level");
                params.add(String.valueOf(quality));
                params.add("-pred");
                params.add("mixed");
                break;
            case WEBP:
                params.add("-quality");
                params.add(String.valueOf(quality));
                params.add("-compression_level");
                params.add("6");
                break;
            default:
                throw new IllegalArgumentException("不支持的格式");
        }
        return params;
    }

    private static void executeCommand(ProcessBuilder pb)
            throws IOException, InterruptedException {
        // 添加命令日志
        System.out.println("[DEBUG] 执行命令: " + String.join(" ", pb.command()));

        // 记录完整输出到文件
        File logFile = new File("ffmpeg_error.log");
        pb.redirectError(logFile);

        try {
            Process process = pb.start();
            StringBuilder output = new StringBuilder();


            BufferedReader reader = null;
            try {
                reader = new BufferedReader(
                        new InputStreamReader(process.getInputStream()));
                String line;
                while ((line = reader.readLine()) != null) {
                    output.append(line).append("\n");
                }
            } finally {
                if (reader != null) {
                    reader.close();
                }
            }

            int exitCode = process.waitFor();
            if (exitCode != 0) {
                String errorContent = FileUtils.readFileToString(logFile, "UTF-8");
                throw new IOException("FFmpeg错误详情:\n" + errorContent);
            }
            if (exitCode != 0) {
                throw new IOException("FFmpeg执行失败:\n" +
                        "命令: " + String.join(" ", pb.command()) + "\n" +
                        "输出: " + output.toString());
            }
        } catch (IOException e) {
            if (e.getMessage().contains("Cannot run program")) {
                throw new IOException("FFmpeg未安装或路径未配置", e);
            }
            throw e;
        }
    }

    public static String getExtensionFromPath(String fileName) {

            int lastDot = fileName.lastIndexOf('.');
            if (lastDot == -1 || lastDot == fileName.length() - 1) return "";

            String[] parts = fileName.substring(lastDot + 1).split("[:?]");
            return parts[0].toLowerCase();
    }
    public static void compressByQuality(String inputPath, String outputPath, float quality)
            throws IOException {
        File inputFile = new File(inputPath);
//        BufferedImage image = ImageIO.read(inputFile);
        RenderedImage image = ImageIO.read(inputFile);

        Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpg");
        ImageWriter writer = writers.next();

        try (ImageOutputStream ios = ImageIO.createImageOutputStream(new File(outputPath))) {
            writer.setOutput(ios);
            ImageWriteParam param = writer.getDefaultWriteParam();
            param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
            param.setCompressionQuality(quality);
            writer.write(null, new IIOImage(image, null, null), param);
        }
        writer.dispose();
    }


    public static void main(String[] args) {
        try {
//            compressByQuality("", "D:/wwb/1/fc_image/compressed/output.jpg", 0.7f);
            // 原始图片路径
            String srcImgPath = "D:/wwb/1/fc_image/uncompressed/2025/4/29/c24af52fdf9f4950abc50fa79417824e.png";
            // 压缩后图片路径
            String destImgPath = "D:/wwb/1/fc_image/compressed/c24af52fdf9f4950abc50fa79417824e.png";
            // 压缩比例，例如0.5表示压缩到原始尺寸的50%
            double scale = 0.5;

//            System.out.println(ImageIO.read(new File(srcImgPath)));

            Thumbnails.of(srcImgPath).scale(1f).outputQuality(0.1).toFile(destImgPath);

//            ImgUtil.scale(FileUtil.file(srcImgPath), FileUtil.file(destImgPath), (float) scale);



//            compressImage(
//                    "D:/wwb/1/fc_image/uncompressed/2025/4/29/0bc833ef66cc4c45a45442c5f8d32264.jpg",
//                    "D:/wwb/1/fc_image/compressed/output.jpg",
//                    85
//            );
//            System.out.println("压缩成功！");
        } catch (Exception e) {
            e.printStackTrace();
            // 查看生成的 ffmpeg_error.log 获取详细信息
        }
    }
}